#pragma once
#include <assert.h>
namespace bit
{
	template<class T>// 当一个类不想要访问限定符限制的时候就用struct
    // 注意：如果这里写成了class 就是模板了 模板是不会被编译的只有在实例化的时候才会
	struct ListNode //不能用class，因为要用友元公有化成员变量和成员函数
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;

		T _data;

		//书写其构造函数，则下面的 _head = new Node() 里面要加参数
		ListNode(const T& data = T()) //写成全缺省，避免下面的不带参问题
			:_next(nullptr)
			, _prev(nullptr)
			,_data(data)
		{}
	};
    // 通过模板，给不同的模板参数，让编译器帮我们实例化两个类
	template<class T, class Ref, class Ptr>  //避免写两次差不多代码
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T, Ref, Ptr> Self;
		Node* _node;

		ListIterator(Node* node)
			:_node(node)
		{}

		// ++it;
		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		Self operator++(int)// 后置++ 不能用引用返回了 tmp会销毁
		{
			Self tmp(*this);
			_node = _node->_next;

			return tmp;
		}

		Self& operator--(int)
		{
			Self tmp(*this);
			_node = _node->_prev;

			return tmp;
		}

		Ref operator*()
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &_node->_data;
		}

		bool operator!=(const Self& it)
		{
			return _node != it._node;
		}

		bool operator==(const Self& it)
		{
			return _node == it._node;
		}
	};

	///*由于Node*不符合遍历的行为，因为Node*为自定义类型，必须要有内置类型，才能通过编译
	//Listlterator类封装Node*
	//再通过重载运算符控制其行为*/
	//template<class T>
	//class ListConstIterator  //class 封装迭代器，控制其行为
	//{
	//	typedef ListNode<T> Node;
	//	typedef  ListConstIterator<T> Self;

	//	Node* _node;
	//	
	//public:
	//	ListConstIterator(Node *node)
	//		:_node(node)
	//	{}

	//	//前置 ++it
	//	Self& operator++() //自加遍历
	//	{
	//		_node = _node->_next; //往后走
	//		return *this;
	//	}

	//	Self& operator--() 
	//	{
	//		_node = _node->_prev; //往前走
	//		return *this;
	//	}

	//     //两个区别：后置不能直接引用返回,而且后置括号中有int进行区分
	//	//后置 就不能引用返回了
	//	Self operator++(int)
	//	{
	//		Self tmp(*this);
	//		_node = _node->_next;
	//		return tmp;
	//	}

	//	Self& operator--(int)
	//	{
	//		Self tmp(*this);
	//		_node = _node->_prev;
	//		return tmp;
	//	}

	//	const T& operator*() //解引用
	//	{
	//		return _node->_data;
	//	}

	//	const T* operator->()
	//	{
	//		return &_node->_data;
	//	}

	//	bool operator!=(const Self& it)
	//	{
	//		return _node != it._node;
	//	}

	//	bool operator == (const Self& it)
	//	{
	//		return _node == it._node;
	//	}

	//};

	 
	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		//不符合迭代器行为，无法遍历
		//typedef Node* iterator;
		
		//自己实现两个类，但是代码冗余
		//typedef ListIterator<T> iterator;
		//typedef ListConstIterator<T> const_iterator;

		//通过模板，给不同模板参数，让编译器帮我们写两个类（实例化）
		typedef ListIterator<T, T&, T*> iterator;
		typedef ListIterator<T, const T&, const T*> const_iterator;

		iterator begin()
		{
			//iterator it(_head->_next);
			//return it;
			
			return iterator(_head->_next);
		}

		//const iterator const  迭代器不能是普通迭代器前面加const修饰
		//const iterator begin() const //用const iterator变成const迭代器不行
		//{
		//	return iterator(_head->_next);
		//}

		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}


		iterator end()
		{
			return iterator(_head);
		}

		const_iterator end() const
		{
			return const_iterator(_head);
		}

		list() //初始化
		{
			//这里没有合适的默认构造函数可以用,可以使用匿名对象，或者上面的listNode写成全缺省
			//_head = new Node(T());
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
		}

		void push_back(const T&x) //尾插
		{
			/*Node* newnode = new Node(x);
			Node* tail = _head->_prev;

			tail->_next = newnode;
			newnode->_prev = tail;

			newnode->_next = _head;
			_head->_prev = newnode;*/
			insert(end(), x);
		}

		void pop_back()
		{
			erase(--end());
		}

		void push_front(const T& x)
		{
			insert(begin(), x);
		}

		void pop_front()
		{
			erase(begin() );
		}

		//没有iterator失效
		//为防止迭代器失效，需要用 iterator返回
		iterator insert(iterator pos, const T& x)
		{
			Node* newnode = new Node(x);
			Node* cur = pos._node; //获取当前位置节点
			Node* prev = cur->_prev;

			//prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;

			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}

		//为防止迭代器失效，需要用 iterator返回
		//erase后pos失效，pos 指向节点被释放
		iterator erase(iterator pos)
		{
			assert(pos != end());
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;

			delete cur;
			return iterator(next);
		}

	private:
		Node* _head;
	};

	// ——————————————————————————

	void Func(const list<int> &lt) //const 迭代器
	{
		//const iterator const  迭代器不能是普通迭代器前面加const修饰
		//const 迭代器目标本身可以修改，指向内容不可以修改，类似于const T* p
		//const list<int>::iterator it = lt.begin(); //那么it无法++，因为const改变
		
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			//指向的内容不能修改
			//*it += 10;

			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test_list1()
	{
		//用于检查最上面的struct和class，细节不会被编译，模板才会
		//按需实例化（不调用就不实例化这个成员函数）
		list<int> l1;
		l1.push_back(1);
		l1.push_back(2);
		l1.push_back(3);
		l1.push_back(4);
		l1.push_back(5);

		Func(l1);

		//迭代器遍历
		// ListIterator<int> it = l1.begin();
		list<int>::iterator it = l1.begin();
		while (it != l1.end())
		{
			*it += 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : l1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

   //二维坐标
	struct Pos 
	{
		int _row;
		int _col;

		//用T实例化，必须提供默认构造
		Pos(int row = 0, int col = 0)
			:_row(row)
			,_col(col)
		{}

	};

	void test_list2()
	{
		list<Pos>l1;
		l1.push_back(Pos(100, 100));
		l1.push_back(Pos(200, 200));
		l1.push_back(Pos(300, 400));
		list<Pos>::iterator it = l1.begin();

		//传值返回产生的临时对象不能引用访问
		//list<Pos>::iterator& it = l1.begin();

		//++为非const，可以用
		//list<Pos>::iterator it = ++l1.begin();


		while (it != l1.end())
		{
			//cout << (*it)._row << ":" << (*it)._col <<endl;
			//结构体或者共有类可以用箭头去访问
			cout << it->_row << ":" << it->_col << endl;
			//为了可读性省略了一个 ->
			//cout << it->->_row << ":" << it->->_col << endl;
			cout << it.operator->()->_row << ":" << it.operator->()->_col << endl; //本质，operator返回pos*
			++it;
		}
		cout << endl;

	}


	void test_list3()
	{
		list<int> l1;
		l1.push_back(1);
		l1.push_back(2);
		l1.push_back(3);
		l1.push_back(4);
		l1.push_back(5);

		Func(l1);

		l1.push_front(10);
		l1.push_front(20);
		l1.push_front(30);

		Func(l1);

		l1.pop_front();
		l1.pop_front();
		Func(l1);

		l1.pop_back();
		l1.pop_back();
		Func(l1);

		//避免删除哨兵点
		l1.pop_back();
		l1.pop_back(); 
		l1.pop_back();
		l1.pop_back();
		l1.pop_back();
		Func(l1);
	}
}
